@******************************************************************************
@ init.S
@ 功能：OpenOCD先将init.bin下载到Steppingstone(内部RAM)中，初始化SDRAM等
@       然后就可以将bootloader直接下载到SDRAM中运行
@******************************************************************************       
#include "lowlevel_init.h"

.text 
.global _start 
_start:
Reset: 
	/* set the cpu to SVC32 mode */
	mrs r0, CPSR
    bic r0, r0, #0x1f
    orr r0, r0, #0xd3
    msr CPSR_fc, r0     @ Supervisor mode, sets the I and F bits

	/* turn off the watchdog */
    ldr r0, =pWTCON
	mov r1, #0
    str r1, [r0]        @ disable WTCON

	/* mask all IRQs by setting all bits in the INTMR - default */
    mvn r1, #0
    ldr r0, =INTMSK
	str r1, [r0]        @ INTMSK = 0xFFFFFFFF

	ldr r1, =0x000007fff
    ldr r0, =INTSUBMSK
    str r1, [r0]        @ INTSUBMSK = 0x000007fff

	/* Set system clock
	 * FCLK:HCLK:PCLK = 1:4:8
	 * FCLK=400MHz，HCLK=100MHz，PCLK=50MHz
	 */
	ldr r0, =CLKDIVN
	mov r1, #5
	str r1, [r0]

/*	set Clocking modes : Asynchronous
 *
 *	if HDIVN is not 0, the CPU bus mode has to be changed
 *	from the fast bus mode to the asynchronous bus mode
 *	and S3C2440 does not support synchronous bus mode
 */
    mrc 15, 0, r1, cr1, cr0, 0            @ read ctrl register
    orr r1, r1, #0xc0000000               @ Asynchronous bus mode
    mcr 15, 0, r1, cr1, cr0, 0            @ write ctrl register

/* 
Setup PLL CONTROL REGISTER
NOTE: When you set MPLL&UPLL values
	  you have to set the UPLL value first and then the MPLL value.
	  (Needs intervalsapproximately 7 NOP )

Fout = 2 * m * Fin / (p*2^S)
FVCO = 2 * m * Fin / p

where: m=MDIV+8, p=PDIV+2, s=SDIV

recommendation table by sumsung:
Input Frequency Output-Frequency  MDIV		PDIV	SDIV
12.0000MHz		405.00 MHz		  127(0x7f)  2		 1
12.0000MHz		532.00 MHz		  125(0x7d)	 1		 1
*/
	ldr r1, =MPLLCON
	mov r2, #MDIV_405MHZ
	add r2, r2, #PSDIV_405MHZ
	str r2, [r1]

	/*
	 * flush v4 I/D caches ,flush TLB
	 */
	mov r0, #0
	mcr 15, 0, r0, cr7, cr7, 0    @ invalidate I,D caches on v4
	mcr 15, 0, r0, cr8, cr7, 0    @ invalidate I,D TLBs on v4

	/*
	 * disable MMU stuff and caches
	 */
    mrc 15, 0, r0, cr1, cr0, 0    @ get control register v4, read control register P539
    bic r0, r0, #0x00002300       @ V[bit[13]]
								  @(Base location of exception registers)=0 = Low addresses = 0x0000 0000
                                  @ R(ROM protection bit[9])=0
                                  @ S(System protection bit[8])=0
                                  @ 由于TTB中AP=0b11(line141)，所以RS位不使用
    bic r0, r0, #0x00000087
                                  @ M(bit[0])=0 = MMU disabled
                                  @ A(bit[1])=0 =Data address alignment fault checking disable
                                  @ C(bit[2])=0 = Data cache disabled
                                  @ B(bit[7])=0 = Little-endian operation
    orr r0, r0, #0x00000002       @ /* .... .... .... ..1. */
									/*A(bit[1])=1 = Data address alignment fault checking enable*/
    orr r0, r0, #0x00001000       @ /* ...1 .... .... .... */
									/*I(bit[12])=1 = Instruction cache enabled*/
    mcr 15, 0, r0, cr1, cr0, 0    @ /* write control register */
									/*write control register P545*/

    @ set memory control registers
    ldr r1, =BWSCON		/* Bus Width Status Controller */
    adrl  r2, SMRDATA
    add r3, r1, #52
1:  ldr r4, [r2], #4
    str r4, [r1], #4
    cmp r1, r3
    bne 1b

/* Light LEDs */
leds_flicker:
    ldr r2, =0x56000010   @ GPBCON
    mov r3, #((1<<(5*2)) | (1<<(6*2)) | (1<<(7*2)) | (1<<(8*2)))      @ GPB5_out|GPB6_out|GPB7_out|GPB8_out
    str r3, [r2]

    ldr r5, =0x56000014   @ GPBDAT  
    mov  r4, #0  @ 0x0

led_loop:
    ldr r0, =DELAY_COUNT
    bl  wait

    mvn r3, r4, lsl #5
    add r4, r4, #1      @ 0x1
    cmp r4, #16 @ 0x10
    subeq r4, r4, #16     @ 0x10
    str r3, [r5]
    b led_loop

wait:
    subs r0, r0, #1
    bne wait
    mov pc, lr

	.ltorg

SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0xb1	/*memory map 64MB SDRAM*/
    .word 0x30  /*set CAS latency 2 clocks*/
    .word 0x30  /*set CAS latency 2 clocks*/
